package com.qdlc.p2p.biz.executer;

import java.util.Map;

import com.qdlc.p2p.common.util.BigDecimalUtil;
import com.qdlc.p2p.dal.common.NoticeTypeHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.dto.Operator;
import com.qdlc.p2p.dal.dto.User;

/**
 * 执行器抽象类
 *
 * @author Kaiju Zhao
 * @date 2016-03-17
 * @version 1.1.0.0
 */
public abstract class AbstractExecuter implements Executer {

	/** 网址地址 */
	protected static String WEB_URL = SystemConfigHelper.getValue(SystemConfigHelper.Nid.WEB_URL);

	/* 交易方 */
	protected User user;

	/*  操作人员 */
	protected Operator operator;

	/* 交易对方 */
	protected User toUser;

	/* 交易金额 */
	protected double money;

	/* 总金额 */
	protected double total;

	/* 可用金额 */
	protected double useMoney;

	/* 冻结金额 */
	protected double noUseMoney;

	/**
	 * 逻辑执行之前的准备工作
	 *
	 * @author Kaiju Zhao
	 */
	public abstract void prepare();

	/**
	 * 新增资金记录
	 *
	 * @author Kaiju Zhao
	 */
	public abstract void addAccountLog();

	/**
	 * 处理用户资金并保存相应记录
	 *
	 * @author Kaiju Zhao
	 */
	public abstract void handleAccountWithLog();

	/**
	 * 处理通知
	 *
	 * @author Kaiju Zhao
	 */
	public abstract void handleNotice();

	/**
	 * 新增操作记录
	 *
	 * @author Kaiju Zhao
	 */
	public abstract void addOperateLog();

	/**
	 * 逻辑执行之后的处理工作
	 *
	 * @author Kaiju Zhao
	 */
	public abstract void extend();
	
	/**
	 * 发送Notice(短信、邮件、站内信)
	 *
	 * @author Kaiju Zhao
	 * @param user 交易方
	 * @param noticeTypeNid notice模版nid
	 * @param nidType notice类型
	 * @param sendData 发送数据
	 */
	protected void sendNotice(User user, String noticeTypeNid){
		sendNotice(user, noticeTypeNid, null);
	}

	/**
	 * 发送Notice(短信、邮件、站内信)
	 *
	 * @author Kaiju Zhao
	 * @param user 交易方
	 * @param noticeTypeNid notice模版nid
	 * @param nidType notice类型
	 * @param sendData 发送数据
	 */
	protected void sendNotice(User user, String noticeTypeNid, NoticeTypeHelper.NidType nidType, Map<String, Object> sendData){
		NoticeExecutor noticeExecutor = new NoticeExecutor(noticeTypeNid, nidType);
		if(sendData != null){
			noticeExecutor.addSendData(sendData);
		}
		noticeExecutor.execute(user);
	}

	/**
	 * 发送Notice(短信、邮件、站内信)
	 *
	 * @author Kaiju Zhao
	 * @param user 交易方
	 * @param noticeTypeNid notice模版nid
	 * @param sendData 发送数据
	 */
	protected void sendNotice(User user, String noticeTypeNid, Map<String, Object> sendData){
		sendNotice(user, noticeTypeNid, null, sendData);
	}

	/**
	 * 执行
	 *
	 * @author Kaiju Zhao
	 * @param money 交易金额
	 * @param total 总额
	 * @param useMoney 可用金额
	 * @param noUseMoney 冻结总额
	 * @param user 交易方
	 * @param toUser 交易对方
	 */
	private void execute(double money, double total, double useMoney, double noUseMoney, User user, User toUser, Operator operator) {
		this.money = BigDecimalUtil.round(money, 2);
		this.total = BigDecimalUtil.round(total, 2);
		this.useMoney = BigDecimalUtil.round(useMoney, 2);
		this.noUseMoney = BigDecimalUtil.round(noUseMoney, 2);
		this.user = user;
		this.toUser = toUser;
		this.operator = operator;
		executeTemplte();
	}

	/**
	 * 执行模板
	 *
	 * @author Kaiju Zhao
	 */
	private void executeTemplte() {
		// 业务预处理
		prepare();
		// 更新账户
		handleAccountWithLog();
		// 添加资金记录
		addAccountLog();
		// 通知处理
		handleNotice();
		// 操作日志记录记录
		addOperateLog();
		// 扩展处理
		extend();
	}

	@Override
	public void execute(double money, User user) {
		execute(money, 0, 0, 0, user, null, null);
	}

	@Override
	public void execute(double money, User user, User toUser) {
		execute(money, 0, 0, 0, user, toUser, null);
	}

	@Override
	public void execute(double total, double useMoney, double noUseMoney, User user, User toUser) {
		execute(0, total, useMoney, noUseMoney, user, toUser, null);
	}

	@Override
	public void execute(double money, User user, Operator operator) {
		execute(money, 0, 0, 0, user, null, operator);
	}

	@Override
	public void execute(double money, User user, Operator operator, User toUser) {
		execute(money, 0, 0, 0, user, toUser, operator);
	}

}
